package it.polimi.travelDreamEJB.basicproductmanagement;

import it.polimi.travelDreamEJB.basicproductmanagement.dto.ExcursionDTO;
import it.polimi.travelDreamEJB.basicproductmanagement.dto.FlightDTO;
import it.polimi.travelDreamEJB.basicproductmanagement.dto.HotelDTO;
import it.polimi.travelDreamEJB.basicproductmanagement.dto.SearchExcursionDTO;
import it.polimi.travelDreamEJB.basicproductmanagement.dto.SearchFlightDTO;
import it.polimi.travelDreamEJB.basicproductmanagement.dto.SearchHotelDTO;
import it.polimi.travelDreamEJB.defaultpacketmanagement.dto.DefaultPacketDTO;
import it.polimi.travelDreamEJB.personalizedpacketmanagement.PersonalizedPacketMgr;
import it.polimi.travelDreamEJB.personalizedpacketmanagement.dto.PersonalizedPacketDTO;
import it.polimi.travelDreamEJB.travelpacketmanagement.DefaultPacket;
import it.polimi.travelDreamEJB.travelpacketmanagement.DefaultPacketMgrBean;
import it.polimi.travelDreamEJB.travelpacketmanagement.PersonalizedPacket;
import it.polimi.travelDreamEJB.travelpacketmanagement.PersonalizedPacketMgrBean;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;


/**
 * Session Bean implementation class BasicProductMgrBean
 */
@Stateless
public class BasicProductMgrBean implements BasicProductMgr{
	
	@PersistenceContext
    private EntityManager em;
	
	@Resource
	private EJBContext context;

    /**
     * Default constructor. 
     */
    public BasicProductMgrBean() {
    }

	@Override
	public void save_hotel(HotelDTO hotel) {
		Hotel newHotel = new Hotel(hotel);
		em.persist(newHotel);
	}

	@Override
	public void save_flight(FlightDTO flight) {
		Flight newFlight = new Flight(flight);
		em.persist(newFlight);
	}

	@Override
	public void save_excursion(ExcursionDTO excursion) {
		Excursion newExcursion = new Excursion(excursion);
		em.persist(newExcursion);
	}

	@Override
	public void update_hotel(HotelDTO hotel) {
		em.merge(new Hotel(hotel));
	}

	@Override
	public void update_flight(FlightDTO flight) {
		em.merge(new Flight(flight));
	}

	@Override
	public void update_excursion(ExcursionDTO excursion) {
		em.merge(new Excursion(excursion));
	}

	@Override
	public void delete_hotel(HotelDTO hotel) {	
		Hotel h = em.find(Hotel.class,hotel.getId());
		em.remove(h);	
	}

	@Override
	public void delete_flight(FlightDTO flight) {
		Flight f = em.find(Flight.class, flight.getId());
		em.remove(f);
	}

	@Override
	public void delete_excursion(ExcursionDTO excursion) {
		Excursion e = em.find(Excursion.class, excursion.getId());
		em.remove(e);
	}

	@Override
	public HotelDTO getHotelDTO() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public FlightDTO getFlightDTO() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ExcursionDTO getExcursionDTO() {
		// TODO Auto-generated method stub
		return null;
	}
	
	public List<String> possibleCities(){
		List<Hotel> hotelCities=em.createNamedQuery("Hotel.possibleCities", Hotel.class).getResultList();
		List<Flight> flightDestinationCities=em.createNamedQuery("Flight.destinationCities", Flight.class).getResultList();
		List<Flight> flightDepartureCities=em.createNamedQuery("Flight.departureCities", Flight.class).getResultList();
		
		List<String> hCities = new ArrayList<String>();
		List<String> destCities = new ArrayList<String>();
		List<String> depCities = new ArrayList<String>();
		
		while(!hotelCities.isEmpty()){
			hCities.add(hotelCities.remove(0).getDestination());
		}
		while(!flightDepartureCities.isEmpty()){
			depCities.add(flightDepartureCities.remove(0).getDeparture());
		}
		while(!flightDestinationCities.isEmpty()){
			destCities.add(flightDestinationCities.remove(0).getDestination());
		}
		
		 
		
		return intersection(intersection(hCities, depCities), destCities);
		
	}
	
	private List<String> intersection(List<String> list1, List<String> list2) {
        List<String> list = new ArrayList<String>();

        for (String t : list1) {
            if(list2.contains(t)) {
                list.add(t);
            }
        }

        return list;
    }
	
	public List<HotelDTO> findHotel(SearchHotelDTO searchHotel){
		
		List<HotelDTO> hotelDTOList = new ArrayList<HotelDTO>();
		List<Hotel> hotelList = findHotelDB(searchHotel);
		
		while( !hotelList.isEmpty() ){
			
			hotelDTOList.add(convertHotelToDTO(hotelList.remove(0)));
			
		}
		
		return hotelDTOList;
		
	}

	@Override
	public List<FlightDTO> findFlight(SearchFlightDTO searchFlight) {
		
		List<FlightDTO> flightDTOList = new ArrayList<FlightDTO>();
		List<Flight> flightList = findFlightDB(searchFlight);
		
		while( !flightList.isEmpty() ){
			
			flightDTOList.add(convertFlightToDTO(flightList.remove(0)));
			
		}
		
		return flightDTOList;
		
	}

	@Override
	public List<ExcursionDTO> findExcursion(SearchExcursionDTO searchExcursion) {
		
		List<ExcursionDTO> excursionDTOList = new ArrayList<ExcursionDTO>();
		List<Excursion> excursionList = findExcursionDB(searchExcursion);
		
		while( !excursionList.isEmpty() ){
			
			excursionDTOList.add(convertExcursionToDTO(excursionList.remove(0)));
			
		}
		
		return excursionDTOList;
		
	}
	
	private List<Hotel> findHotelDB(SearchHotelDTO searchHotel){
		
		Query query = em.createNamedQuery("Hotel.find", Hotel.class);
		query.setParameter("destination", "%" + searchHotel.getDestination() + "%");
		query.setParameter("name", "%" + searchHotel.getName() + "%");
		query.setParameter("minPrice", searchHotel.getMinPrice());
		query.setParameter("maxPrice", searchHotel.getMaxPrice());
		query.setParameter("minStars", searchHotel.getMinStars());
		query.setParameter("maxStars", searchHotel.getMaxStars());
		List<Hotel> resultList = query.getResultList();
		return resultList;
		
	}
	
	private List<Flight> findFlightDB(SearchFlightDTO searchFlight){
		
		Query query = em.createNamedQuery("Flight.find", Flight.class);
		query.setParameter("airline", "%" + searchFlight.getAirline() + "%");
		query.setParameter("departure", "%" + searchFlight.getDeparture() + "%");
		query.setParameter("departure_airport", "%" + searchFlight.getDeparture_airport() + "%");
		query.setParameter("destination", "%" + searchFlight.getDestination() + "%");
		query.setParameter("destination_airport", "%" + searchFlight.getDestination_airport() + "%");
		query.setParameter("fromFlightDate", searchFlight.getFromFlightDate());
		query.setParameter("toFlightDate", searchFlight.getToFlightDate());
		query.setParameter("minPrice", searchFlight.getMinPrice());
		query.setParameter("maxPrice", searchFlight.getMaxPrice());
		List<Flight> resultList = query.getResultList();
		return resultList;
		
	}
	
	private List<Excursion> findExcursionDB(SearchExcursionDTO searchExcursion){
		
		Query query = em.createNamedQuery("Excursion.find", Excursion.class);
		query.setParameter("destination", "%" + searchExcursion.getDestination() + "%");
		query.setParameter("name", "%" + searchExcursion.getName() + "%");
		query.setParameter("info", "%" + searchExcursion.getInfo() + "%");
		query.setParameter("minPrice", searchExcursion.getMinPrice());
		query.setParameter("maxPrice", searchExcursion.getMaxPrice());
		List<Excursion> resultList = query.getResultList();
		return resultList;
		
	}
	
	static public HotelDTO convertHotelToDTO(Hotel hotel){
		
		HotelDTO hotelDTO = new HotelDTO();
		hotelDTO.setId(hotel.getIdHotel());
		hotelDTO.setDestination(hotel.getDestination());
		hotelDTO.setInfo(hotel.getInfo());
		hotelDTO.setName(hotel.getName());
		hotelDTO.setPrice(hotel.getPrice());
		hotelDTO.setStars(hotel.getStars());
		
		return hotelDTO;
		
	}
	
	static public FlightDTO convertFlightToDTO(Flight flight){
			
		FlightDTO flightDTO = new FlightDTO();
		flightDTO.setId(flight.getIdFlight());
		flightDTO.setAirline(flight.getAirline());
		flightDTO.setDeparture(flight.getDeparture());
		flightDTO.setDeparture_airport(flight.getDepartureAirport());
		flightDTO.setDestination(flight.getDestination());
		flightDTO.setDestination_airport(flight.getDestinationAirport());
		flightDTO.setFlightDate(flight.getFlightDate());
		flightDTO.setPrice(flight.getPrice());
		
		return flightDTO;
		
	}
	
	static public ExcursionDTO convertExcursionToDTO(Excursion excursion){
		
		ExcursionDTO excursionDTO = new ExcursionDTO();
		excursionDTO.setId(excursion.getIdExcursion());
		excursionDTO.setDestination(excursion.getDestination());
		excursionDTO.setInfo(excursion.getInfo());
		excursionDTO.setName(excursion.getName());
		excursionDTO.setPrice(excursion.getPrice());
		
		return excursionDTO;
	}
	
}